package com.apestech.framework.xml.condition.modul;

import com.apestech.api.condition.Step.StepLifeCycleInter;
import com.apestech.framework.json.JSON;
import com.apestech.framework.json.JSONArray;
import com.apestech.framework.json.JSONObject;
import com.apestech.framework.util.StringUtil;
import com.apestech.framework.util.callback.SpiltStrCallback;

import java.util.ArrayList;

/**
 * @author hup
 * @create 2019-02-28-10:56
 */
public class ConditionStrategy extends StringUtil{

    public static class Field {
        private String id;
        private String name;
        private String target;
        private String result;
        private String express;
        private String defaultField;
        private String defaultValue;

        public Field(JSONObject map){
            id=map.getString("id");
            name=map.getString("name");
            target=map.getString("target");
            result=map.getString("result");
            express=map.getString("express");
            defaultField=map.getString("defaultField");
            defaultValue=map.getString("default");
        }

        public String getId() {
            return id;
        }

        public String getResult() {
            return result;
        }

        public String getExpress() {
            return express;
        }

        public String getDefaultField() {
            return defaultField;
        }

        public String getDefaultValue() {
            return defaultValue;
        }

        public String getName() {
            return name;
        }

        public String getTarget() {
            if(target==null) target=result;
            if(target==null) target=id;
            return target;
        }
    }

    public static class Then {
        private boolean bBreak=false;
        private ArrayList<Step> then=new ArrayList<Step>();
        private String msg;

        public Then(JSONObject map){
            if(map==null){
                map=new JSONObject();
            }
            bBreak="1".equals(map.getString("break"));
            msg=map.getString("msg");
        }

        public boolean isbBreak() {
            return bBreak;
        }

        public ArrayList<Step> getThen() {
            return then;
        }

        public void setThen(ArrayList<Step> then) {
            this.then = then;
        }

        public void addStep(JSONObject map){
            then.add(new Step(map));
        }

        public void addStep(Step step){
            then.add(step);
        }

        public String getMsg() {
            return msg;
        }
    }

    public static class If {
        private String name;
        private String exp;
        private boolean bElse=false;
        private Then fthen;
        private If fif;
        private Then ethen;

        public If(JSONObject map){
            if(map==null) return;
            name=map.getString("name");
            exp=map.getString("express");
            bElse="else".equals(map.getString("type"));
        }

        public String getExp() {
            return exp;
        }

        public void setExp(String exp) {
            this.exp = exp;
        }

        public String getName() {
            return name;
        }

        public boolean isbElse() {
            return bElse;
        }

        public void setbElse(boolean bElse) {
            this.bElse = bElse;
        }

        public Then getFthen() {
            return fthen;
        }

        public void setFthen(Then fthen) {
            this.fthen = fthen;
        }

        public If getFif() {
            return fif;
        }

        public void setFif(If fif) {
            this.fif = fif;
        }

        public Then getEthen() {
            return ethen;
        }

        public void setEthen(Then ethen) {
            this.ethen = ethen;
        }
    }

    public static class While {
        private String name;
        private String resultKey;
        private Step sql;
        private ArrayList<Step> step=new ArrayList<Step>();
        private JSONObject reslut;

        public While(JSONObject map){
            name=map.getString("name");
            resultKey=map.getString("resultKey");
        }

        public String getName() {
            return name;
        }

        public String getResultKey() {
            return resultKey;
        }

        public Step getSql() {
            return sql;
        }

        public void setSql(Step sql) {
            this.sql = sql;
        }

        public ArrayList<Step> getStep() {
            return step;
        }

        public void setStep(ArrayList<Step> step) {
            this.step = step;
        }

        public void addStep(JSONObject map){
            step.add(new Step(map));
        }

        public void addStep(Step sstep){
            step.add(sstep);
        }

        public Step getLastStep(){
            int len=step.size();
            if(len==0) return null;
            return step.get(len-1);
        }

        public void setLastStep(Step steps) {
            int len=step.size();
            if(len==0) return;
            step.set(len-1, steps);
        }

        public JSONObject getReslut() {
            return reslut;
        }

        public void setReslut(JSONObject reslut) {
            this.reslut = reslut;
        }
    }

    public static class Step {
        private String type;
        private String id;
        private String name;
        private String noFoundMsg;
        private String outputfields;
        private String noNullField;  //通过定义获取
        private String inputfields;
        private String express;
        private String result;
        private ArrayList<Field> inputs=new ArrayList<Field>();
        private ArrayList<Field> outputs=new ArrayList<Field>();
        private JSONObject resultMap;
        private JSONArray resultList;
        private StepLifeCycleInter stepLife;
        private String mustInput;
        private JSONObject allOutputDef;
        private JSONObject allInputDef;
        private boolean isbreak=false;
        private String sql;
        private String from;
        private String sqlfrom;
        private String sumId;
        private String tabname;
        private While fwhile;
        private If fif;
        private String field;
        private boolean bPrint=false;
        private String db;
        private boolean istrans=false;
        private String xlsReadFile;

        private boolean alldata=false;
        private String mutikey;
        private boolean isremove=false;
        private String value;
        private JSONObject other=new JSONObject();
        private String nullValue;
        private boolean oneRecord=false;

        private String cid;
        private String dimfield;

        private JSONObject superInput=new JSONObject();
        private Step pstep;
        private ArrayList<Step> steps=new ArrayList<Step>();

        public Step(Step step){
            type=step.type;
            id=step.id;
            name=step.name;
            noFoundMsg=step.noFoundMsg;
            outputfields=step.outputfields;
            noNullField=step.noNullField;
            inputfields=step.inputfields;
            express=step.express;
            result=step.result;
            inputs=step.inputs;
            outputs=step.outputs;
            resultMap=null;
            resultList=step.resultList;
            stepLife=step.stepLife;
            mustInput=step.mustInput;
            allOutputDef=new JSONObject(step.allOutputDef);
            allInputDef=new JSONObject(step.allInputDef);
            isbreak=step.isbreak;
            sql=step.sql;
            from=step.from;
            sqlfrom=step.sqlfrom;
            sumId=step.sumId;
            tabname=step.tabname;
            fwhile=step.fwhile;
            fif=step.fif;
            field=step.field;
            bPrint=step.bPrint;
            db=step.db;
            istrans=step.istrans;
            xlsReadFile=step.xlsReadFile;
            alldata=step.alldata;
            mutikey=step.mutikey;
            isremove=step.isremove;
            value=step.value;
            other=new JSONObject(step.other);
            nullValue=step.nullValue;
            oneRecord=step.oneRecord;
            cid=step.cid;
            dimfield=step.dimfield;
        }

        public Step(JSONObject map){
            ArrayList<String> klist=map.getKeylist();
            int len=klist.size();
            for(int i=0; i<len; i++){
                String k=klist.get(i);
                switch (k){
                    case "type":{
                        type=map.getString(k);
                        break;
                    }
                    case "id":{
                        id=map.getString(k);
                        break;
                    }
                    case "name":{
                        name=map.getString(k);
                        break;
                    }
                    case "msg":{
                        noFoundMsg=map.getString(k);
                        break;
                    }
                    case "outputfields":{
                        outputfields=map.getString(k);
                        break;
                    }
                    case "inputfields":{
                        inputfields=map.getString(k);
                        break;
                    }
                    case "express":{
                        express=map.getString(k);
                        break;
                    }
                    case "result":{
                        result=map.getString(k);
                        break;
                    }
                    case "sql":{
                        sql=map.getString(k);
                        break;
                    }
                    case "db":{
                        db=map.getString(k);
                        break;
                    }
                    case "from":{
                        from=map.getString(k);
                        break;
                    }
                    case "sqlfrom":{
                        sqlfrom=map.getString(k);
                        break;
                    }
                    case "sumId":{
                        sumId=map.getString(k);
                        break;
                    }
                    case "tabname":{
                        tabname=map.getString(k);
                        break;
                    }
                    case "field":{
                        field=map.getString(k);
                        break;
                    }
                    case "nullValue":{
                        nullValue=map.getString(k);
                        break;
                    }
                    case "xlsReadFile":{
                        xlsReadFile=map.getString(k);
                        if(xlsReadFile!=null){
                            xlsReadFile=getVarKey(xlsReadFile);
                        }
                        break;
                    }
                    case "print":{
                        bPrint="1".equals(map.getString(k));
                        break;
                    }
                    case "break":{
                        isbreak="1".equals(map.getString(k));
                        break;
                    }
                    case "trans":{
                        istrans="1".equals(map.getString(k));
                        break;
                    }
                    case "remove":{
                        isremove="1".equals(map.getString(k));
                        break;
                    }
                    case "value":{
                        value=map.getString(k);
                        break;
                    }
                    case "alldata":{
                        alldata="1".equals(map.getString(k));
                        break;
                    }
                    case "mutikey":{
                        mutikey=map.getString(k);
                        break;
                    }
                    case "oneRecord":{
                        oneRecord="1".equals(map.getString(k));
                        break;
                    }
                    case "cid":{
                        cid=map.getString(k);
                        break;
                    }
                    case "dimfield":{
                        dimfield=map.getString(k);
                        break;
                    }
                    default:{
                        other.put(k, map.getString(k));
                    }
                }
            }
            if((",condition,queryid,sql,insert,update,delete,save,while,json,xls,if,conditionStrategy,array,").indexOf(","+type+",")<0){
                type="field";
            }
            resultMap=null;
        }

        public void addInputField(JSONObject map){
            addInputField(new Field(map));
        }

        public void addInputField(Field field){
            inputs.add(field);
        }

        public void addOutputField(JSONObject map){
            addOutputField(new Field(map));
        }

        public void addOutputField(Field field){
            outputs.add(field);
        }

        public void setNoNullField(String noNullField) {
            this.noNullField = noNullField;
        }

        public String getId() {
            return id;
        }

        public String getNoFoundMsg() {
            return noFoundMsg;
        }

        public String getOutputfields() {
            if(outputfields!=null && "".equals(outputfields.trim())) return null;
            return outputfields;
        }

        public String getNoNullField() {
            return noNullField;
        }

        public String getType() {
            return type;
        }

        public String getDb() {
            return db;
        }

        public String getInputfields() {
            if(inputfields!=null && "".equals(inputfields.trim())) return null;
            return inputfields;
        }

        public String getName() {
            return name;
        }

        public JSONObject getResultMap() {
            return resultMap;
        }

        public void setResultMap(JSONObject resultMap) {
            this.resultMap = resultMap;
        }

        public JSONArray getResultList() {
            return resultList;
        }

        public void setResultList(JSONArray resultList) {
            this.resultList = resultList;
        }

        public String getExpress() {
            return express;
        }

        public String getResult() {
            return result;
        }

        public boolean isIsbreak() {
            return isbreak;
        }

        public ArrayList<Field> getInputs() {
            return inputs;
        }

        public ArrayList<Field> getOutputs() {
            return outputs;
        }

        public StepLifeCycleInter getStepLife() {
            return stepLife;
        }

        public void setStepLife(StepLifeCycleInter stepLife) {
            this.stepLife = stepLife;
        }

        public String getMustInput() {
            return mustInput;
        }

        public void setMustInput(String mustInput) {
            this.mustInput = mustInput;
        }

        public String getSql() {
            return sql;
        }

        public String getFrom() {
            return from;
        }

        public String getSqlfrom() {
            return sqlfrom;
        }

        public String getSumId() {
            return sumId;
        }

        public String getTabname() {
            return tabname;
        }

        public While getFwhile() {
            return fwhile;
        }

        public void setFwhile(While fwhile) {
            this.fwhile = fwhile;
        }

        public If getFif() {
            return fif;
        }

        public void setFif(If fif) {
            this.fif = fif;
        }

        public String getField() {
            return field;
        }

        public String getXlsReadFile() {
            return xlsReadFile;
        }

        public boolean isbPrint() {
            return bPrint;
        }

        public boolean isIstrans() {
            return istrans;
        }

        public void setIstrans(boolean istrans) {
            this.istrans = istrans;
        }

        public boolean isIsremove() {
            return isremove;
        }

        public String getValue() {
            return value;
        }

        public JSONObject getOther() {
            return other;
        }

        public boolean isAlldata() {
            return alldata;
        }

        public String getMutikey() {
            return mutikey;
        }

        public String getNullValue() {
            return nullValue;
        }

        public String getCid() {
            return cid;
        }

        public String getDimfield() {
            return dimfield;
        }

        public boolean isOneRecord() {
            return oneRecord;
        }

        public void setOneRecord(boolean oneRecord) {
            this.oneRecord = oneRecord;
        }

        public JSONObject getAllInputDef() throws Exception {
            if(allInputDef==null){
                allInputDef=new JSONObject();
                execSplitStr(inputfields, ",", new SpiltStrCallback(){
                    @Override
                    public void exec(String id) throws Exception {
                        JSONObject m=new JSONObject();
                        m.put("id", id);
                        m.put("target", id);
                        allInputDef.put(id, new Field(m));
                    }
                });
                if(inputs!=null) {
                    int len=inputs.size();
                    for(int i=0; i<len; i++){
                        Field f=inputs.get(i);
                        allInputDef.put(f.getId(), f);
                    }
                }
            }
            return allInputDef;
        }

        public JSONObject getAllOutputDef() throws Exception {
            if(allOutputDef==null){
                allOutputDef=new JSONObject();
                execSplitStr(outputfields, ",", new SpiltStrCallback(){
                    @Override
                    public void exec(String id) throws Exception {
                        JSONObject m=new JSONObject();
                        m.put("id", id);
                        m.put("target", id);
                        allOutputDef.put(id, new Field(m));
                    }
                });
                if(outputs!=null) {
                    int len=outputs.size();
                    for(int i=0; i<len; i++){
                        Field f=outputs.get(i);
                        allOutputDef.put(f.getId(), f);
                    }
                }
            }
            return allOutputDef;
        }

        public JSONObject getSuperInput() {
            return superInput;
        }

        public void setSuperInput(JSONObject superInput) {
            this.superInput = superInput;
        }

        public Step getPstep() {
            return pstep;
        }

        public void setPstep(Step pstep) {
            this.pstep = pstep;
        }
    }

    private String id;
    private String name;
    private String defaultValue;
    private String billField;
    private boolean bConcurrency=false;
    private JSONObject stepIndex=new JSONObject();
    private ArrayList<Step> steps=new ArrayList<Step>();
    private JSONObject must_input=new JSONObject();

    public ConditionStrategy(){
    }

    public ConditionStrategy(ConditionStrategy conditionStrategy){
        this.id=conditionStrategy.getId();
        this.name=conditionStrategy.getName();
        this.defaultValue=conditionStrategy.getDefaultValue();
        this.billField=conditionStrategy.getBillField();
        this.bConcurrency=conditionStrategy.isbConcurrency();
        this.stepIndex=new JSONObject(conditionStrategy.getStepIndex());
        this.must_input=new JSONObject(conditionStrategy.getMust_input());
        steps=new ArrayList<Step>();
        int len=conditionStrategy.getSteps().size();
        for(int i=0; i<len; i++){
            steps.add(new Step(conditionStrategy.getSteps().get(i)));
        }
    }

    public void setConditionStrategy(JSONObject map){
        id=map.getString("id");
        name=map.getString("name");
        billField=map.getString("billField");
        bConcurrency="1".equals(map.getString("concurrency"));
        ArrayList<String> klist=map.getKeylist();
        int len=klist.size();
        for(int i=0; i<len; i++){
            String k=klist.get(i);
            int klen=k.length();
            int pos=k.indexOf("default_");
            if(pos>=0){
                defaultValue=leftStr(k, klen-pos-8);
                break;
            }
        }
    }

    public Step addStep(JSONObject map){
        Step step=new Step(map);
        steps.add(step);
        String key=map.getString("type")+"."+map.getString("id");
        stepIndex.put(key, steps.size()-1);
        return step;
    }

    public void addField(JSONObject map){
        Step step=null;
        int len=steps.size();
        if(len>0){
            step=steps.get(steps.size()-1);
        } else {
            step=new Step(map);
        }
        step.addOutputField(map);
    }

    public Step getStep(String id) throws Exception {
        Integer inx=stepIndex.getInteger(id);
        if(inx==null) return null;
        return steps.get(inx);
    }

    public Step getLastStep() throws Exception {
        int len=steps.size();
        if(len==0) return null;
        return steps.get(len-1);
    }

    public void setLastStep(Step step) {
        int len=steps.size();
        if(len==0) return;
        steps.set(len-1, step);
    }

    public String getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public String getDefaultValue() {
        return defaultValue;
    }

    public ArrayList<Step> getSteps() {
        return steps;
    }

    public int getStepIndex(String key) {
        if(stepIndex.get(key)==null) return -1;
        return (int) stepIndex.get(key);
    }

    public boolean isbConcurrency() {
        return bConcurrency;
    }

    public String getBillField() {
        return billField;
    }

    public JSONObject getStepIndex() {
        return stepIndex;
    }

    public JSONObject getMust_input() {
        return must_input;
    }

    public void setMust_input(JSONObject must_input) throws Exception {
        this.must_input = new JSONObject(must_input);
        for(String k: this.must_input.getKeylist()){
            JSONObject map=JSON.toJSON(this.must_input.get(k));
            if(map.get("name")!=null){
                map.put("comment", map.get("name"));
            }
            this.must_input.put(k, map);
        }

    }


}
